/*!
 * \file TraderAdapter.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief UFT交易适配器头文件，定义了TraderAdapter类和TraderAdapterMgr类
 * 
 * \details 本文件包含超高频交易系统中的交易适配器实现。
 *          TraderAdapter类封装了交易接口API，提供统一的交易操作接口。
 *          TraderAdapterMgr类负责管理多个交易适配器实例。
 *          支持多种交易操作：开仓、平仓、撤单等，并提供仓位管理和订单状态跟踪功能。
 */
#pragma once

#include "../Includes/FasterDefs.h"
#include "../Includes/ITraderApi.h"
#include "../Share/BoostFile.hpp"
#include "../Share/StdUtils.hpp"
#include "../Includes/WTSCollection.hpp"

NS_WTP_BEGIN
class WTSVariant;
class WTSContractInfo;
class WTSCommodityInfo;
class ITrdNotifySink;
class ActionPolicyMgr;

typedef std::vector<uint32_t> OrderIDs;
typedef WTSMap<uint32_t> OrderMap;

/*!
 * \class TraderAdapter
 * \brief UFT交易适配器类
 * 
 * \details 交易适配器是UFT系统中的核心组件，负责：
 *          - 封装底层交易API接口
 *          - 提供统一的交易操作接口（开仓、平仓、撤单等）
 *          - 管理仓位信息和订单状态
 *          - 处理交易回调事件
 *          - 支持多种交易模式（FAK、FOK等）
 *          - 提供风险控制和交易限制检查
 * 
 * \note 该类继承自ITraderSpi，用于接收交易API的回调通知
 * \warning 所有交易操作都需要在登录成功后进行
 */
class TraderAdapter : public ITraderSpi
{
public:
	TraderAdapter();
	~TraderAdapter();

	/*!
	 * \enum tagAdapterState
	 * \brief 交易适配器状态枚举
	 * 
	 * \details 定义了交易适配器的各种状态，用于跟踪适配器的连接和初始化状态
	 */
	typedef enum tagAdapterState
	{
		AS_NOTLOGIN,		///<未登录状态
		AS_LOGINING,		///<正在登录状态
		AS_LOGINED,			///<已登录状态
		AS_LOGINFAILED,		///<登录失败状态
		AS_POSITION_QRYED,	///<仓位已查询状态
		AS_ORDERS_QRYED,	///<订单已查询状态
		AS_TRADES_QRYED,	///<成交已查询状态
		AS_ALLREADY			///<全部就绪状态
	} AdapterState;

	/*!
	 * \struct _PosItem
	 * \brief 仓位项结构体
	 * 
	 * \details 用于存储某个合约的完整仓位信息，包括多头和空头的持仓数量和可用数量
	 */
	typedef struct _PosItem
	{
		//多头持仓
		double	l_newvol;		///<多头今仓数量
		double	l_newavail;		///<多头今仓可用数量
		double	l_prevol;		///<多头昨仓数量
		double	l_preavail;		///<多头昨仓可用数量

		//空头持仓
		double	s_newvol;		///<空头今仓数量
		double	s_newavail;		///<空头今仓可用数量
		double	s_prevol;		///<空头昨仓数量
		double	s_preavail;		///<空头昨仓可用数量

		/*!
		 * \brief 构造函数，初始化所有字段为0
		 */
		_PosItem()
		{
			memset(this, 0, sizeof(_PosItem));
		}

		/*!
		 * \brief 获取总持仓数量
		 * \param isLong 是否为多头，true-多头，false-空头
		 * \return 返回总持仓数量（今仓+昨仓）
		 */
		double total_pos(bool isLong = true) const
		{
			if (isLong)
				return l_newvol + l_prevol;
			else
				return s_newvol + s_prevol;
		}

		/*!
		 * \brief 获取可用持仓数量
		 * \param isLong 是否为多头，true-多头，false-空头
		 * \return 返回可用持仓数量（今仓可用+昨仓可用）
		 */
		double avail_pos(bool isLong = true) const
		{
			if (isLong)
				return l_newavail + l_preavail;
			else
				return s_newavail + s_preavail;
		}

	} PosItem;


public:
	/*!
	 * \brief 初始化交易适配器
	 * \param id 适配器ID
	 * \param params 配置参数
	 * \param bdMgr 基础数据管理器
	 * \param policyMgr 动作策略管理器
	 * \return 初始化成功返回true，失败返回false
	 * 
	 * \details 从配置参数中加载交易模块，创建交易API实例并进行初始化
	 */
	bool init(const char* id, WTSVariant* params, IBaseDataMgr* bdMgr, ActionPolicyMgr* policyMgr);

	/*!
	 * \brief 扩展初始化方法
	 * \param id 适配器ID
	 * \param api 已创建的交易API实例
	 * \param bdMgr 基础数据管理器
	 * \param policyMgr 动作策略管理器
	 * \return 初始化成功返回true，失败返回false
	 * 
	 * \details 使用外部提供的交易API实例进行初始化，适用于API实例复用场景
	 */
	bool initExt(const char* id, ITraderApi* api, IBaseDataMgr* bdMgr, ActionPolicyMgr* policyMgr);

	/*!
	 * \brief 释放资源
	 * 
	 * \details 注销交易回调，释放交易API资源
	 */
	void release();

	/*!
	 * \brief 启动交易适配器
	 * \return 启动成功返回true，失败返回false
	 * 
	 * \details 注册交易回调，连接交易服务器，开始登录流程
	 */
	bool run();

	/*!
	 * \brief 获取适配器ID
	 * \return 返回适配器ID字符串
	 */
	inline const char* id() const{ return _id.c_str(); }

	/*!
	 * \brief 获取适配器当前状态
	 * \return 返回适配器状态枚举值
	 */
	AdapterState state() const{ return _state; }

	/*!
	 * \brief 添加交易通知接收器
	 * \param sink 交易通知接收器指针
	 * 
	 * \details 添加的接收器将接收所有交易相关的事件通知
	 */
	void addSink(ITrdNotifySink* sink)
	{
		_sinks.insert(sink);
	}

private:
	/*!
	 * \brief 执行委托下单
	 * \param entrust 委托单信息
	 * \return 返回本地订单ID
	 * 
	 * \details 内部方法，将委托单提交给底层交易API
	 */
	uint32_t doEntrust(WTSEntrust* entrust);
	
	/*!
	 * \brief 执行撤单操作
	 * \param ordInfo 订单信息
	 * \return 撤单成功返回true，失败返回false
	 * 
	 * \details 内部方法，向底层交易API提交撤单请求
	 */
	bool	doCancel(WTSOrderInfo* ordInfo);

	/*!
	 * \brief 打印仓位信息
	 * \param stdCode 标准合约代码
	 * \param pItem 仓位项信息
	 * 
	 * \details 内部方法，用于调试输出仓位详情
	 */
	inline void	printPosition(const char* stdCode, const PosItem& pItem);

	/*!
	 * \brief 获取合约信息
	 * \param stdCode 标准合约代码
	 * \return 返回合约信息指针
	 * 
	 * \details 内部方法，从基础数据管理器获取合约详情
	 */
	inline WTSContractInfo* getContract(const char* stdCode);

	/*!
	 * \brief 更新未成交数量
	 * \param stdCode 标准合约代码
	 * \param qty 数量
	 * \param bOuput 是否输出日志，默认true
	 * 
	 * \details 内部方法，更新指定合约的未成交委托数量统计
	 */
	inline void updateUndone(const char* stdCode, double qty, bool bOuput = true);

public:
	/*!
	 * \brief 获取持仓数量
	 * \param stdCode 标准合约代码
	 * \param bValidOnly 是否只返回有效持仓
	 * \param flag 持仓标志，3-总持仓，1-多头，2-空头
	 * \return 返回持仓数量
	 * 
	 * \details 根据参数获取指定合约的持仓信息
	 */
	double	getPosition(const char* stdCode, bool bValidOnly, int32_t flag = 3);
	
	/*!
	 * \brief 枚举持仓
	 * \param stdCode 标准合约代码，空字符串表示所有合约
	 * \return 返回持仓总值
	 * 
	 * \details 遍历所有或指定合约的持仓，返回持仓总值
	 */
	double	enumPosition(const char* stdCode = "");
	
	/*!
	 * \brief 获取订单映射
	 * \param stdCode 标准合约代码
	 * \return 返回该合约的订单映射指针
	 */
	OrderMap* getOrders(const char* stdCode);
	
	/*!
	 * \brief 获取未成交数量
	 * \param stdCode 标准合约代码
	 * \return 返回未成交数量
	 * 
	 * \details 查询指定合约当前的未成交委托数量
	 */
	double getUndoneQty(const char* stdCode)
	{
		auto it = _undone_qty.find(stdCode);
		if (it != _undone_qty.end())
			return it->second;

		return 0;
	}

	/*!
	 * \brief 买入操作（通用接口）
	 * \param stdCode 标准合约代码
	 * \param price 价格，0表示市价
	 * \param qty 数量
	 * \param flag 订单标志：0-normal，1-fak，2-fok
	 * \param bForceClose 是否强制平仓
	 * \param cInfo 合约信息，可选
	 * \return 返回订单ID列表
	 * 
	 * \details 智能买入，根据当前持仓情况自动判断是开仓还是平仓
	 */
	OrderIDs buy(const char* stdCode, double price, double qty, int flag, bool bForceClose, WTSContractInfo* cInfo = NULL);
	
	/*!
	 * \brief 卖出操作（通用接口）
	 * \param stdCode 标准合约代码
	 * \param price 价格，0表示市价
	 * \param qty 数量
	 * \param flag 订单标志：0-normal，1-fak，2-fok
	 * \param bForceClose 是否强制平仓
	 * \param cInfo 合约信息，可选
	 * \return 返回订单ID列表
	 * 
	 * \details 智能卖出，根据当前持仓情况自动判断是开仓还是平仓
	 */
	OrderIDs sell(const char* stdCode, double price, double qty, int flag, bool bForceClose, WTSContractInfo* cInfo = NULL);

	/*!
	 * \brief 开多仓接口
	 * \param stdCode 合约代码
	 * \param price 下单价格，0表示市价单
	 * \param qty 下单数量
	 * \param flag 下单标志: 0-normal，1-fak，2-fok
	 * \return 返回本地订单ID
	 *	
	 * \details 直接开立多头仓位的接口
	 */
	uint32_t openLong(const char* stdCode, double price, double qty, int flag);

	/*!
	 * \brief 开空仓接口
	 * \param stdCode 合约代码
	 * \param price 下单价格，0表示市价单
	 * \param qty 下单数量
	 * \param flag 下单标志: 0-normal，1-fak，2-fok
	 * \return 返回本地订单ID
	 * 
	 * \details 直接开立空头仓位的接口
	 */
	uint32_t openShort(const char* stdCode, double price, double qty, int flag);

	/*!
	 * \brief 平多仓接口
	 * \param stdCode 合约代码
	 * \param price 下单价格，0表示市价单
	 * \param qty 下单数量
	 * \param isToday 是否平今，默认false
	 * \param flag 下单标志: 0-normal，1-fak，2-fok，默认0
	 * \return 返回本地订单ID
	 * 
	 * \details 平掉多头仓位的接口，支持平今和平昨选择
	 */
	uint32_t closeLong(const char* stdCode, double price, double qty, bool isToday, int flag);

	/*!
	 * \brief 平空仓接口
	 * \param stdCode 合约代码
	 * \param price 下单价格，0表示市价单
	 * \param qty 下单数量
	 * \param isToday 是否平今，默认false
	 * \param flag 下单标志: 0-normal，1-fak，2-fok，默认0
	 * \return 返回本地订单ID
	 * 
	 * \details 平掉空头仓位的接口，支持平今和平昨选择
	 */
	uint32_t closeShort(const char* stdCode, double price, double qty, bool isToday, int flag);
	
	/*!
	 * \brief 撤单接口
	 * \param localid 本地订单ID
	 * \return 撤单成功返回true，失败返回false
	 * 
	 * \details 根据本地订单ID撤销指定订单
	 */
	bool	cancel(uint32_t localid);
	
	/*!
	 * \brief 撤销所有订单
	 * \param stdCode 标准合约代码
	 * \return 返回被撤销的订单ID列表
	 * 
	 * \details 撤销指定合约的所有未成交订单
	 */
	OrderIDs cancelAll(const char* stdCode);

	/*!
	 * \brief 检查是否允许交易
	 * \param stdCode 标准合约代码
	 * \return 允许交易返回true，否则返回false
	 * 
	 * \details 检查指定合约是否在可交易状态
	 */
	inline bool	isTradeEnabled(const char* stdCode) const;

	//bool	checkCancelLimits(const char* stdCode);
	//bool	checkOrderLimits(const char* stdCode);

public:
	//////////////////////////////////////////////////////////////////////////
	//ITraderSpi接口实现
	
	/*!
	 * \brief 处理交易事件
	 * \param e 交易事件类型
	 * \param ec 错误代码
	 * 
	 * \details 处理来自底层交易API的各种事件通知
	 */
	virtual void handleEvent(WTSTraderEvent e, int32_t ec) override;

	/*!
	 * \brief 登录结果回调
	 * \param bSucc 登录是否成功
	 * \param msg 登录消息
	 * \param tradingdate 交易日期
	 * 
	 * \details 处理交易API的登录结果通知
	 */
	virtual void onLoginResult(bool bSucc, const char* msg, uint32_t tradingdate) override;

	/*!
	 * \brief 登出回调
	 * 
	 * \details 处理交易API的登出通知
	 */
	virtual void onLogout() override;

	/*!
	 * \brief 委托回报回调
	 * \param entrust 委托信息
	 * \param err 错误信息
	 * 
	 * \details 处理委托下单的结果回报
	 */
	virtual void onRspEntrust(WTSEntrust* entrust, WTSError *err) override;

	/*!
	 * \brief 账户查询回调
	 * \param ayAccounts 账户信息数组
	 * 
	 * \details 处理账户资金查询的结果
	 */
	virtual void onRspAccount(WTSArray* ayAccounts) override;

	/*!
	 * \brief 持仓查询回调
	 * \param ayPositions 持仓信息数组
	 * 
	 * \details 处理持仓查询的结果，更新内部持仓缓存
	 */
	virtual void onRspPosition(const WTSArray* ayPositions) override;

	/*!
	 * \brief 订单查询回调
	 * \param ayOrders 订单信息数组
	 * 
	 * \details 处理订单查询的结果，更新内部订单缓存
	 */
	virtual void onRspOrders(const WTSArray* ayOrders) override;

	/*!
	 * \brief 成交查询回调
	 * \param ayTrades 成交信息数组
	 * 
	 * \details 处理成交查询的结果，更新交易统计信息
	 */
	virtual void onRspTrades(const WTSArray* ayTrades) override;

	/*!
	 * \brief 订单推送回调
	 * \param orderInfo 订单信息
	 * 
	 * \details 处理实时订单状态变化的推送通知
	 */
	virtual void onPushOrder(WTSOrderInfo* orderInfo) override;

	/*!
	 * \brief 成交推送回调
	 * \param tradeRecord 成交记录
	 * 
	 * \details 处理实时成交信息的推送通知
	 */
	virtual void onPushTrade(WTSTradeInfo* tradeRecord) override;

	/*!
	 * \brief 交易错误回调
	 * \param err 错误信息
	 * 
	 * \details 处理交易过程中的错误通知
	 */
	virtual void onTraderError(WTSError* err) override;

	/*!
	 * \brief 获取基础数据管理器
	 * \return 返回基础数据管理器指针
	 */
	virtual IBaseDataMgr* getBaseDataMgr() override;

	/*!
	 * \brief 处理交易日志
	 * \param ll 日志级别
	 * \param message 日志消息
	 * 
	 * \details 处理来自底层交易API的日志信息
	 */
	virtual void handleTraderLog(WTSLogLevel ll, const char* message) override;

private:
	WTSVariant*			_cfg;				///<配置信息
	std::string			_id;				///<适配器ID
	std::string			_order_pattern;		///<订单模式

	uint32_t			_trading_day;		///<交易日

	ITraderApi*			_trader_api;		///<交易API接口
	FuncDeleteTrader	_remover;			///<删除函数
	AdapterState		_state;				///<适配器状态

	faster_hashset<ITrdNotifySink*>	_sinks;	///<通知接收器集合

	IBaseDataMgr*		_bd_mgr;			///<基础数据管理器
	ActionPolicyMgr*	_policy_mgr;		///<动作策略管理器

	faster_hashmap<std::string, PosItem> _positions;	///<持仓映射

	StdUniqueMutex _mtx_orders;				///<订单锁
	OrderMap*		_orders;				///<订单映射
	faster_hashset<std::string> _orderids;	///<主要用于保存还没有成交回报的订单

	faster_hashmap<LongKey, double> _undone_qty;	///<未成交数量映射

	typedef WTSHashMap<LongKey>	TradeStatMap;
	TradeStatMap*	_stat_map;				///<统计数据映射
};

typedef std::shared_ptr<TraderAdapter>				TraderAdapterPtr;
typedef faster_hashmap<std::string, TraderAdapterPtr>	TraderAdapterMap;


//////////////////////////////////////////////////////////////////////////
//TraderAdapterMgr

/*!
 * \class TraderAdapterMgr
 * \brief 交易适配器管理器类
 * 
 * \details 负责管理多个交易适配器实例，提供适配器的添加、获取、释放等功能。
 *          支持多账户、多通道的交易管理，为上层策略提供统一的交易接口。
 * 
 * \note 该类采用单例模式，全局只有一个管理器实例
 */
class TraderAdapterMgr
{
public:
	/*!
	 * \brief 释放所有适配器资源
	 * 
	 * \details 遍历所有适配器，调用其release方法释放资源
	 */
	void	release();

	/*!
	 * \brief 启动所有适配器
	 * 
	 * \details 遍历所有适配器，调用其run方法启动交易连接
	 */
	void	run();

	/*!
	 * \brief 获取适配器映射
	 * \return 返回只读的适配器映射引用
	 * 
	 * \details 获取当前管理的所有适配器映射，用于遍历或查询
	 */
	const TraderAdapterMap& getAdapters() const { return _adapters; }

	/*!
	 * \brief 获取指定适配器
	 * \param tname 适配器名称
	 * \return 返回适配器智能指针，未找到返回空指针
	 * 
	 * \details 根据名称查找并返回对应的交易适配器实例
	 */
	TraderAdapterPtr getAdapter(const char* tname);

	/*!
	 * \brief 添加适配器
	 * \param tname 适配器名称
	 * \param adapter 适配器智能指针
	 * \return 添加成功返回true，失败返回false
	 * 
	 * \details 将适配器实例添加到管理器中，名称不能重复
	 */
	bool	addAdapter(const char* tname, TraderAdapterPtr& adapter);

private:
	TraderAdapterMap	_adapters;			///<适配器映射表
};

NS_WTP_END
